﻿//-----------------------------------------------------------------------
// <copyright file="DbContextBase.cs" company="SLWY Enterprises">
// * Copyright (C) 2017 四川商旅无忧科技有限公司 版权所有。
// * version : 1.0
// * author  : qinchaoyue
// * FileName: DbContextBase.cs
// * history : created by qinchaoyue 2017-12-14 07:14:11
// </copyright>
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using Slwy.FrameCore.Dependency;
using Microsoft.Extensions.DependencyInjection;
using System.Collections;
using System.Linq;
using Slwy.Data.Entity.Data;
using Slwy.Data.Entity.Interfaces;
using Slwy.Data.Entity.SqlSugarExtensions;
using Slwy.Logger.Contracts;
using Slwy.MySql.Contracts;
using SqlSugar;

namespace Slwy.Data.Entity
{

    /// <summary>
    /// 数据库上下文
    /// </summary>
    public class DbContextBase : IUnitOfWork
    {
        /// <summary>
        /// 日志记录
        /// </summary>
        private readonly ILogger _logger;

        /// <summary>
        /// 写库
        /// </summary>
        // public IDictionary<string, SqlSugarClient> WriteDbSet { get; set; }

        public IDictionary<string, SqlSugarClient> DbSet { get; set; }

        /// <summary>
        /// Initializes a new instance 
        /// </summary>
        /// <param name="mySqlConnection">
        /// The my sql connection.
        /// </param>
        /// <param name="logger">
        /// The logger.
        /// </param>
        public DbContextBase(IMySqlConnection mySqlConnection, ILogger logger)
        {
            this._logger = logger;
            GroupConnect(mySqlConnection);
        }

        private void GroupConnect(IMySqlConnection mySqlConnection)
        {
            var connections = mySqlConnection.GetConnections();
            if (!connections.Any())
            {
                throw new ArgumentNullException("获取数据库链接失败, 请确认配置文件是否正确.");
            }
            foreach (var connection in mySqlConnection.GetConnections())
            {
                if (connection.Name.ToUpper().IndexOf("WRITE", StringComparison.Ordinal) != -1)
                {
                    var writeConnectionString = mySqlConnection.GetCustomeConnection(connection.Name).ConnectionString;
                    var readString = 
                        connection.Name.ToUpper().Replace("WRITE", "READ");
                    var readConnectionString = mySqlConnection.GetCustomeConnection(readString).ConnectionString;
                    InitConnect(connection.Name, writeConnectionString, readConnectionString);
                }
            }
        }

        private void InitConnect(string dbName, string writeConnect, string readConnect)
        {
            if (this.DbSet == null)
            {
                this.DbSet = new Dictionary<string, SqlSugarClient>();
            }
            this.DbSet.Add(dbName, new SqlSugarClient
            (
                new ConnectionConfig
                {
                    ConnectionString = writeConnect,
                    DbType = DbType.MySql,
                    IsAutoCloseConnection = true,
                    IsShardSameThread = true,
                    SlaveConnectionConfigs = new List<SlaveConnectionConfig>
                    {
                        new SlaveConnectionConfig
                        {
                            HitRate = 1,
                            ConnectionString = readConnect
                        }
                    }
                }
            ));
        }

        //public void SetConnection(string suffix)
        //{
        //    SetConnection("ConnectionWrite", "ConnectionRead", suffix);
        //}

        //public void SetConnection(string connectWriteName, string connectReadName, string suffix = "")
        //{
        //    var writeMappingTables = this.WriteDbSet.MappingTables;
        //    this.WriteDbSet = new SqlSugarClient(new ConnectionConfig
        //    {
        //        ConnectionString = _mySqlConnection.GetCustomeConnection(connectWriteName, suffix).ConnectionString,
        //        DbType = DbType.MySql,
        //        IsAutoCloseConnection = true,
        //        IsShardSameThread = true,
        //    });
        //    this.WriteDbSet.MappingTables = writeMappingTables;

        //    var readMappingTables = this.ReadDbSet.MappingTables;
        //    this.ReadDbSet = new SqlSugarClient(new ConnectionConfig
        //    {
        //        ConnectionString = _mySqlConnection.GetCustomeConnection(connectReadName, suffix).ConnectionString,
        //        DbType = DbType.MySql,
        //        IsAutoCloseConnection = true,
        //        IsShardSameThread = true
        //    });
        //    this.ReadDbSet.MappingTables = readMappingTables;
        //}

        /// <summary>
        /// 设置事务开关
        /// </summary>
        public void SetTransactionEnabled(bool value, string dbName)
        {
            if (value)
            {
                try
                {
                    this.DbSet[dbName].Ado.BeginTran();
                    if (!this._transactionEnabled.TryGetValue(dbName, out _))
                    {
                        this._transactionEnabled.TryAdd(dbName, true);
                    }
                    else
                    {
                        this._transactionEnabled[dbName] = true;
                    }
                }
                catch (Exception e)
                {
                    this.DbSet[dbName].Ado.RollbackTran();
                    this._transactionEnabled.TryAdd(dbName, false);
                    this._logger.Error(e, "开启事务失败");
                    throw;
                }
            }
        }

        public IDictionary<string, string> DbTables { get; set; }

        /// <summary>
        /// 获取事务开关
        /// </summary>
        /// <param name="dbName"></param>
        /// <returns></returns>
        public bool GetTransactionEnabled(string dbName)
        {
            if (!this._transactionEnabled.TryGetValue(dbName, out var v))
            {
                return false;
            }

            return v;
        }

        /// <summary>
        /// 获取或者设置事务开关
        /// </summary>
        private Dictionary<string, bool> _transactionEnabled = new Dictionary<string, bool>();

        // public event EventHandler OnSaveChange;

        // public event EventHandler SaveChanged;

        private Func<SqlSugarClient, string, bool> _onSaveChanged;
        public Func<SqlSugarClient, string, bool> OnSaveChanged
        {
            get => this._onSaveChanged;
            set => this._onSaveChanged += value;
        }

        public bool SaveChanges(string dbName)
        {
            try
            {
                // this.OnSaveChange?.Invoke(this, null);
                this.DbSet[dbName].Ado.CommitTran();
                this._transactionEnabled[dbName] = false;
            }
            catch (Exception e)
            {
                this.DbSet[dbName].Ado.RollbackTran();
                this._logger.Error(e, "执行事务失败.");
                return false;
            }

            try
            {
                this._onSaveChanged?.Invoke(this.DbSet[dbName], dbName);
            }
            catch
            {
                // 回调失败了不管本类的事,  返回事务执行成功.
                return true;
            }

            return true;
        }
    }
}
